﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Collections;

namespace Dynamo.Core.Materializer
{
	public class Dematerializer : IDematerializer
	{
		private StringBuilder sbObjectData;

		#region IDematerializer Members

		public string Dematerialize(object oObject)
		{
			sbObjectData = new StringBuilder();

			DematerializeObject(oObject);

			return sbObjectData.ToString();
		}

		#endregion

		public void DematerializeObject(object oObject)
		{
			Type tObjectType = oObject.GetType();

			sbObjectData.Append("<");
			sbObjectData.Append(tObjectType.FullName);
			sbObjectData.Append(">");

			foreach (PropertyInfo piPropertyInfo in tObjectType.GetProperties())
			{
				object oPropertyValue = piPropertyInfo.GetValue(oObject, null);

				if (oPropertyValue != null)
				{
					sbObjectData.Append("<");
					sbObjectData.Append(piPropertyInfo.Name);
					sbObjectData.Append(">");

					if (piPropertyInfo.PropertyType == typeof(string) ||
						piPropertyInfo.PropertyType == typeof(int) ||
						piPropertyInfo.PropertyType == typeof(Guid))
					{
						sbObjectData.Append(oPropertyValue);
					}
					else if (typeof(IList).IsAssignableFrom(piPropertyInfo.PropertyType))
					{
						foreach (object oItem in (IList)piPropertyInfo.GetValue(oObject, null))
						{
							DematerializeObject(oItem);
						}
					}
					else if (piPropertyInfo.IsDefined(typeof(ReferenceAttribute), true))
					{
						sbObjectData.Append("<Dynamo.Materializer.Reference>");
						sbObjectData.Append("type=\"");
						sbObjectData.Append(piPropertyInfo.PropertyType);
						sbObjectData.Append("\" id=\"");

						foreach (PropertyInfo piPropertyInfo2 in oPropertyValue.GetType().GetProperties())
						{
							if (piPropertyInfo2.IsDefined(typeof(IdAttribute), true))
							{
								sbObjectData.Append(piPropertyInfo2.GetValue(oPropertyValue, null));
								break;
							}
						}

						sbObjectData.Append("\"");
						sbObjectData.Append("</Dynamo.Materializer.Reference>");
					}
					else
					{
						DematerializeObject(oPropertyValue);
					}

					sbObjectData.Append("</");
					sbObjectData.Append(piPropertyInfo.Name);
					sbObjectData.Append(">");
				}
			}

			sbObjectData.Append("</");
			sbObjectData.Append(tObjectType.FullName);
			sbObjectData.Append(">");
		}
	}
}
